package com.zjx.activiti01;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.*;
import java.util.List;
import java.util.zip.ZipInputStream;

public class ActivitiDemo {

    /**
     * 测试流程部署
     */
    @Test
    public void testDeployment(){
        //1.创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2.获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3.使用service进行流程部署，把bpmn和png部署到数据中
        Deployment deploy = repositoryService.createDeployment().name("出差流程申请").addClasspathResource("bpmn/evetion.bpmn")
                .addClasspathResource("bpmn/evetion.png").deploy();
        //4.输出部署信息
        System.out.println("流程部署ID="+deploy.getId());
        System.out.println("流程部署名字="+deploy.getName());

    }

    /**
     * 使用zip包进行批量的部署
     */
    @Test
    public void deployProcessByZip(){
//        获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
//        流程部署
//        读取资源包文件，构造成inputStream
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("bpmn/evetion.zip");
//        用inputStream 构造ZipInputStream
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
//        使用压缩包的流进行流程的部署
        Deployment deploy = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();
        System.out.println("流程部署id="+deploy.getId());
        System.out.println("流程部署的名称="+deploy.getName());
    }


    /**
     * 启动流程实例
     * `act_hi_actinst`    流程实例执行历史信息
     * `act_hi_identitylink` 流程参与用户的历史信息
     * `act_hi_procinst`     流程实例的历史信息
     * `act_hi_taskinst`     流程任务的历史信息
     * `act_ru_execution`    流程执行信息
     * `act_ru_identitylink`  流程的正在参与用户信息
     * `act_ru_task`         流程当前任务信息
     */
    @Test
    public void testStartProcess(){
        //1.创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //3. 根据流程定义的ID启动流程
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("process_evetion");

        //4.输出内容
        System.out.println("流程定义ID："+instance.getProcessDefinitionId());
        System.out.println("流程实例ID："+instance.getId());
        System.out.println("当前活动ID："+instance.getActivityId());
    }

    /**
     * 查询个人执行的任务
     */
    @Test
    public void testFindPersonalTaskList(){
        //1.获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.获取TaskService
        TaskService taskService = processEngine.getTaskService();

        //3.根据流程key和任务负责人查询任务
        List<Task> tasks = taskService.createTaskQuery()
                .processDefinitionKey("process_evetion")  //流程key
                .taskAssignee("zhangsan")   //要查询的负责人
                .list();

        //4.输出内容
        for(Task task : tasks){
            System.out.println("流程实例ID="+task.getProcessInstanceId());
            System.out.println("任务ID="+task.getId());
            System.out.println("任务负责人="+task.getAssignee());
            System.out.println("任务名称="+task.getName());
        }
    }


    /**
     * 完成个人任务（任务的执行）
     */
    @Test
    public void completTask(){
        //1.获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.获取service
        TaskService taskService = processEngine.getTaskService();

        //根据任务ID完成任务
//        taskService.complete("2505");

        //获取jerry正在执行的process_evetion任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("process_evetion")
                .taskAssignee("jerry")
                .singleResult();

        System.out.println("流程实例ID="+task.getProcessInstanceId());
        System.out.println("任务ID="+task.getId());
        System.out.println("任务负责人="+task.getAssignee());
        System.out.println("任务名称="+task.getName());

        //根据任务ID完成任务
        taskService.complete(task.getId());
    }

    /**
     * 查询流程定义信息
     */
    @Test
    public void queryProcessDefinition(){
        //获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //查询当前所有的流程定义（根据key查询）
        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> definitionList = definitionQuery.processDefinitionKey("process_evetion")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();
        //输出
        for(ProcessDefinition definition : definitionList){
            System.out.println("流程定义ID："+definition.getId());
            System.out.println("流程定义名称："+definition.getName());
            System.out.println("流程定义key："+definition.getKey());
            System.out.println("流程定义版本："+definition.getVersion());
            System.out.println("流程部署ID："+definition.getDeploymentId());
        }
    }

    /**
     * 删除流程部署信息
     * 注意：如果有未完成的流程则删不掉该流程部署信息
     * 如果要删除未完成的流程，则需要使用特殊的删除方式（级联删除）
     */
    @Test
    public void deleteDeployment(){
       //获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //通过流程引擎获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //通过部署ID来删除流程部署信息
        String deploymentId = "15001";
//        repositoryService.deleteDeployment(deploymentId);

        //级联删除
        repositoryService.deleteDeployment(deploymentId,true);
    }

    /**
     * 下载流程资源
     *
     * 方案一：使用activiti提供的API下载资源文件，保存到文件目录 （RepositoryService）
     *
     * 方案二：自己写代码从数据库下载文件，使用jdbc对blob类型数据读取出来，保存到文件目录
     * 解决io操作：commons-io.jar
     *
     * 推荐使用方案一
     */
    @Test
    public void getDeployment() throws IOException {
        // 1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();


        //2、从流程引擎获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3、获取查询对象ProcessDefinitionQuery查询流程定义信息
        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();

        //4、通过流程定义信息获取部署ID
        ProcessDefinition definition = definitionQuery.processDefinitionKey("my-test").singleResult();
        String deploymentId = definition.getDeploymentId();

        //5、通过RepositoryService传递部署ID参数，读取资源信息（png和bpmn）
        //5.1 获取png图片的流
        //从流程定义表中获取png图片的目录和名字
        String pngName = definition.getDiagramResourceName();
        InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
        //5.2获取bpmn的流
        String bpmnName = definition.getResourceName();
        InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);

        //6、构造outputStream
        File pngFile = new File("d:/evetionflow02.png");
        File bpmnFile = new File("d:/evetionflow02.bpmn");
        FileOutputStream pngOutputStrem = new FileOutputStream(pngFile);
        FileOutputStream bpmnOutputStrem = new FileOutputStream(bpmnFile);

        //7、输入流、输出流的转换
        IOUtils.copy(pngInput,pngOutputStrem);
        IOUtils.copy(bpmnInput,bpmnOutputStrem);
        //8、关闭流
        pngOutputStrem.close();
        bpmnOutputStrem.close();
        pngInput.close();
        bpmnInput.close();

    }

    /**
     * 查看历史信息
     */
    @Test
    public void findHistoryInfo(){
        //获取工作流引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();

        //查询actinst表（根据实例ID进行查询）
        instanceQuery.processInstanceId("2501");
        //增加排序，根据开始时间排序
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();

        //查询所有内容
        List<HistoricActivityInstance> list = instanceQuery.list();

        //输出
        for(HistoricActivityInstance instance : list){
            System.out.println(instance.getActivityId());
            System.out.println(instance.getActivityName());
            System.out.println(instance.getProcessDefinitionId());
            System.out.println(instance.getProcessInstanceId());
            System.out.println(instance.getStartTime());
            System.out.println(instance.getEndTime());
            System.out.println("=====================================================");
        }
    }

}
